﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>Notification System</title>
		<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
	</head>

	<body>

		<div class="document-contents">

			<h3>Introduction</h3>
			<p>Notifications are used to <strong>inform</strong> users on specific events in 
the system. ASP.NET Boilerplate provides a
				<strong>pub/sub</strong> based <strong>real time</strong> notification 
infrastructure.</p>
			<h4>Sending Models</h4>
			<p>There are two ways of sending notifications to users:</p>
			<ul>
				<li>User <strong>subscribes</strong> to a specific notification type. 
		Then we <strong>publish</strong> a notification of this type which is 
		delivered to all <strong>subscribed</strong> users. This is the <strong>pub/sub</strong> 
		model.</li>
				<li>We can <strong>directly send</strong> a notification to <strong>
		target user(s)</strong>.</li>
			</ul>
			<h4>Notification Types</h4>
			<p>There are also two types of notifications:</p>
			<ul>
				<li>
					<strong>General notifications</strong> are arbitrary type of 
		notifications. "Notify me if a user sends me a friendship request" is an 
		example of this type notifications.</li>
				<li>
					<strong>Entity notifications</strong> are associated to a 
		specific entity. "Notify me if a user comment on <strong>this</strong> 
		photo" is an entity based notification since it's associated to a 
		specific photo entity. Users may want to get notifications for some 
		photos, not for all.</li>
			</ul>
			<h4>Notification Data</h4>
			<p>A notification generally include a <strong>notification data</strong>. For 
	example: "Notify me if a user sends me a friendship request" notification 
	may have two data properties: <em>sender user name</em> (which user sent 
	this friendship request) and <em>request note</em> (a note that user did 
	write in the request). It's obvious that the notification data type is tightly 
	coupled to notification types. Different notification types have different 
	data types.</p>
			<p>Notification data is <strong>optional</strong>. Some notifications may 
	not require a data. There are some pre-defined notification data types those 
	can be enough for most cases. <strong>MessageNotificationData</strong> can 
	be used for simple messages and <strong>LocalizableMessageNotificationData</strong> 
	can be used for localizable and parametric notification messages. We will 
	see example usage in later sections.</p>
			<h4>Notification Severity</h4>
			<p>There are 5 levels of notification severity, defined in <strong>
	NotificationSeverity</strong> enum: <strong>Info</strong>, <strong>Success</strong>,
				<strong>Warn</strong>, <strong>Error</strong> and <strong>Fatal</strong>. 
	Default value is <strong>Info</strong>.</p>

			<div class="bs-callout bs-callout-warning">
				<h4>About Notification Persistence</h4>
				<p>See <em>Notification Store</em> section for more information on 
	notification 
	persistence.</p>
			</div>

			<h3>Subscribe to Notifications</h3>
			<p>
				<strong>INotificationSubscriptionManager</strong> provides API to <strong>
	subscribe</strong> to notifications. Examples:</p>
			<pre lang="cs">public class MyService : ITransientDependency
{
    private readonly INotificationSubscriptionManager _notificationSubscriptionManager;

    public MyService(<strong>INotificationSubscriptionManager notificationSubscriptionManager</strong>)
    {
        _notificationSubscriptionManager = notificationSubscriptionManager;
    }

    <strong>//Subscribe to a general notification</strong>
    public async Task Subscribe_SentFrendshipRequest(int? tenantId, long userId)
    {
        <strong>await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), &quot;SentFrendshipRequest&quot;);</strong>    
    }

    <strong>//Subscribe to an entity notification</strong>
    public async Task Subscribe_CommentPhoto(int? tenantId, long userId, Guid photoId)
    {
        <strong>await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), &quot;CommentPhoto&quot;, new EntityIdentifier(typeof(Photo), photoId));</strong>   
    }
}</pre>
			<p>First, we <a href="/Pages/Documents/Dependency-Injection">injected</a>
				<strong>INotificationSubscriptionManager</strong>. 
	First method subscribes to a <strong>general notification</strong>. User wants to get notified 
	when someone sends a friendship request. Second one subscribes to a 
	notification related to a <strong>specific entity</strong> (Photo). User wants to get 
	notified if anyone write comment to a specified photo.</p>
			<p>Every notification type should have <strong>unique names</strong> (like
				<em>SentFrendshipRequest</em> 
	and <em>CommentPhoto</em> in the samples)</p>
			<p>
				<strong>INotificationSubscriptionManager</strong> has also <strong>
	UnsubscribeAsync, IsSubscribedAsync, GetSubscriptionsAsync</strong>... 
	methods to manage subscriptions.</p>
			<h3>Publish Notifications</h3>
			<p>
				<strong>INotificationPublisher</strong> is used to publish notifications. 
	Examples:</p>
			<pre lang="cs">public class MyService : ITransientDependency
{
    private readonly INotificationPublisher _notiticationPublisher;

    public MyService(<strong>INotificationPublisher notiticationPublisher</strong>)
    {
        _notiticationPublisher = notiticationPublisher;
    }

    <strong>//Send a general notification to a specific user</strong>
    public async Task Publish_SentFrendshipRequest(string senderUserName, string friendshipMessage, UserIdentifier targetUserId)
    {
        <strong>await _notiticationPublisher.PublishAsync(&quot;SentFrendshipRequest&quot;, new SentFrendshipRequestNotificationData(senderUserName, friendshipMessage), userIds: new[] { targetUserId });</strong>
    }

    <strong>//Send an entity notification to a specific user</strong>
    public async Task Publish_CommentPhoto(string commenterUserName, string comment, Guid photoId, UserIdentifier photoOwnerUserId)
    {
        <strong>await _notiticationPublisher.PublishAsync(&quot;CommentPhoto&quot;, new CommentPhotoNotificationData(commenterUserName, comment), new EntityIdentifier(typeof(Photo), photoId), userIds: new[] { photoOwnerUserId });</strong>
    }

    <strong>//Send a general notification to all subscribed users in current tenant (tenant in the session)</strong>
    public async Task Publish_LowDisk(int remainingDiskInMb)
    {
        //<span lang="tr">Example "</span>LowDiskWarningMessage<span lang="tr">" content for</span> English -&gt; &quot;Attention! Only {remainingDiskInMb} MBs left on the disk!&quot;
        <strong>var data = new LocalizableMessageNotificationData(new LocalizableString(&quot;LowDiskWarningMessage&quot;, &quot;MyLocalizationSourceName&quot;));
        data[&quot;remainingDiskInMb&quot;] = remainingDiskInMb;

        await _notiticationPublisher.PublishAsync(&quot;System.LowDisk&quot;, data, severity: NotificationSeverity.Warn);</strong>    
    }
}</pre>
			<p>In the first example, we published a notification to a single user. 
				<em>SentFrendshipRequestNotificationData</em> should be derived from <strong>
	NotificationData</strong> like that:</p>
			<pre lang="cs">[Serializable]
public class SentFrendshipRequestNotificationData : <strong>NotificationData</strong>
{
    public string SenderUserName { get; set; }

    public string FriendshipMessage { get; set; }

    public SentFrendshipRequestNotificationData(string senderUserName, string friendshipMessage)
    {
        SenderUserName = senderUserName;
        FriendshipMessage = friendshipMessage;
    }
}</pre>
			<p>In the second example, we sent a notification to a <strong>specific user</strong> 
	for a <strong>specific entity</strong>. Notification data classes don't need 
	to be <strong>serialzable</strong> normally (since JSON serialization is 
	used by default). But it's suggested to mark it as serializable since you 
	may need to move notifications between applications and may want to use 
	binary serialization in the future. Also, as declared before, notification 
	data is optional and may not be required for all notifications.</p>
			<p>
				<strong>Note</strong>: If we publish a notification to <strong>specific 
	users</strong>, they <strong>don't need</strong> to be subscribed to those 
	notifications.</p>
			<p>In the third example, we did not define a dedicated notification data 
	class. instead, directly used built-in <strong>
	LocalizableMessageNotificationData </strong>with <strong>dictionary</strong> based data and published notification as '<strong>Warn</strong>'. <strong>
	LocalizableMessageNotificationData </strong>can store dictionary-based arbitrary data (this is also true for custom 
	notification data classes since they also inherit from <strong>NotificationData</strong> 
	class). We used "<strong>remainingDiskInMb</strong>" as argument on
				<a href="/Pages/Documents/Localization">localization</a>. Localization message can include these arguments (like &quot;<em>Attention! Only {remainingDiskInMb} MBs left on the disk!</em>&quot; 
	in the example). We will see how to localize it in the Client Side section.</p>
			<h3>User Notification Manager</h3>
			<p>
				<strong>IUserNotificationManager</strong> is used to manage notifications 
	of users. It has methods to <strong>get</strong>, <strong>update</strong> or 
				<strong>delete</strong> notifications for a 
	user. You can use it to prepare a notification list page for your 
	application.</p>
			<h3>Real Time Notifications</h3>
			<p>While you can use IUserNotificationManager to query notifications, we 
	generally want to push real time notifications to the client.</p>
			<p>Notification system uses <strong>IRealTimeNotifier</strong> to send real 
	time notifications to users. This can be implemented with any type of real 
	time communication system. It's implemented using <strong>SignalR</strong> 
	in a seperated package. <a href="/Templates">Startup templates</a> have 
	already SignalR installed. See
				<a href="/Pages/Documents/SignalR-Integration">SignalR Integration document</a> 
	for more information.</p>
			<p>
				<strong>Note</strong>: Notification system calls <strong>
	IRealTimeNotifier</strong> asynchronously in a
				<a href="/Pages/Documents/Background-Jobs-And-Workers">
					<strong>background 
	job</strong>
				</a>. So, notifications may be sent with a small delay.</p>
			<h4>Client Side</h4>
			<p>When a real time notification is received, ASP.NET Boilerplate triggers a <strong>global event</strong> in the client side. 
	You can register like that to get notifications:</p>
			<pre lang="js">abp.event.on(&#39;<strong>abp.notifications.received</strong>&#39;, function (userNotification) {
    console.log(userNotification);
});</pre>
			<p>
				<strong>abp.notifications.received</strong> event is triggered for each 
	received real time notification. You can register to this event as shown 
	above to get notifications. See
				<a href="/Pages/Documents/Javascript-API/Event-Bus">javascript event bus</a> 
	documentation for more information on events. An example incoming 
	notification JSON for "System.LowDisk" example:</p>
			<pre lang="js">{
    "userId": 2,
    "state": 0,
    "notification": {
        "notificationName": "System.LowDisk",
        "data": {
            "message": {
                "sourceName": "MyLocalizationSourceName",
                "name": "LowDiskWarningMessage"
            },
            "type": "Abp.Notifications.LocalizableMessageNotificationData",
            "properties": {
                "remainingDiskInMb": "42"
            }
        },
        "entityType": null,
        "entityTypeName": null,
        "entityId": null,
        "severity": 0,
        "creationTime": "2016-02-09T17:03:32.13",
        "id": "0263d581-3d8a-476b-8e16-4f6a6f10a632"
    },
    "id": "4a546baf-bf17-4924-b993-32e420a8d468"
}</pre>
			<p>In this object;</p>
			<ul>
				<li>
					<strong>userId</strong>: Current user id. Generally you don't need 
		this since you know the current user.</li>
				<li>
					<strong>state</strong>: Value of <strong>UserNotificationState</strong> 
		enum. 0: <strong>Unread</strong>, 1: <strong>Read</strong>.</li>
				<li>
					<strong>notification</strong>: Notification details.<ul>
						<li>
							<strong>notificationName</strong>: Unique name of the 
			notification (same value used while publishing the notification).</li>
						<li>
							<strong>data</strong>: notification data. In this example, we 
			used <strong>
	LocalizableMessageNotificationData </strong>(as published in the example 
			before).<ul>
								<li>
									<strong>message</strong>: Localizable message information. 
				We can use <strong>sourceName</strong> and <strong>name</strong> 
				to localize message on the UI.</li>
								<li>
									<strong>type</strong>: Notification data type. Full type 
				name, including namespaces. We can check this type while 
				processing the notification data.</li>
								<li>
									<strong>properties</strong>: Dictionary based custom 
				properties.</li>
							</ul>
						</li>
						<li>
							<strong>entityType</strong>, <strong>entityTypeName</strong> and
							<strong>entityId</strong>: Entity information if this is an entity 
			related notification.</li>
						<li>
							<strong>severity</strong>: Value of <strong>NotificationSeverity</strong> 
			enum. 0: <strong>Info</strong>, 1: <strong>Success</strong>, 2:
							<strong>Warn</strong>, 3: <strong>Error</strong>, 4: <strong>Fatal</strong>.</li>
						<li>
							<strong>creationTime</strong>: Time of when this notification is 
			created.</li>
						<li>
							<strong>id</strong>: Notification id.</li>
					</ul>
				</li>
				<li>
					<strong>id</strong>: User notification id.</li>
			</ul>
			<p>Surely, you will not just log the notification. You can use notification 
	data to show notification information to the user. Example:</p>
			<pre lang="js">abp.event.on(&#39;<strong>abp.notifications.received</strong>&#39;, function (userNotification) {
    if (userNotification.notification.data.<strong>type</strong> === &#39;<strong>Abp.Notifications.LocalizableMessageNotificationData</strong>&#39;) {
        var localizedText = abp.localization.localize(
            userNotification.notification.data.message.<strong>name</strong>,
            userNotification.notification.data.message.<strong>sourceName</strong>
        );

        $.each(userNotification.notification.data.properties, function (key, value) {
            localizedText = localizedText.replace(&#39;{&#39; + key + &#39;}&#39;, value);
        });

        alert(&#39;New localized notification: &#39; + localizedText);
    } else if (userNotification.notification.data.<strong>type</strong> === &#39;<strong>Abp.Notifications.MessageNotificationData</strong>&#39;) {
        alert(&#39;New simple notification: &#39; + userNotification.notification.data.<strong>message</strong>);
    }
});</pre>
			<p>To be able to process notification data, we should check the data type. 
	This example simply gets message from notification data. For the localized 
	message (LocalizableMessageNotificationData), we are localizing the message 
	and replacing parameters. For simple message (MessageNotificationData), we 
	directly get the message. Surely, in a real project, we will not use alert 
	function. We can use <a href="/Pages/Documents/Javascript-API/Notification">
	abp.notify</a> api to show nice UI notifications.</p>
			<p>If you need to implement such a logic above, there is an easier and 
	scaleable way. You can just use single line of code to show a 
				<a href="/Pages/Documents/Javascript-API/Notification">UI 
	notification</a> when a push notification is received:</p>
			<pre lang="js">abp.event.on('abp.notifications.received', function (userNotification) {
    <strong>abp.notifications.showUiNotifyForUserNotification(userNotification);</strong>
});</pre>
			<p>This shows a <a href="/Pages/Documents/Javascript-API/Notification">UI 
	notification</a> like that (for System.LowDisk notification published above):</p>
			<p>
				<img alt="" height="86" src="images/notification-warn.png" width="314" />
			</p>
			<p>It works for built-in notification data types (LocalizableMessageNotificationData 
	and MessageNotificationData). If you have custom notification data types, 
	then you should register data formatters like that:</p>
			<pre lang="js">abp.notifications.messageFormatters['MyProject.MyNotificationDataType'] = function(userNotification) {
    return ...; //format and return message here
};</pre>
			<p>Thus,
				<strong>showUiNotifyForUserNotification</strong>
	can create shown messages for your data types. If you just need to the 
	formatted message, you can directly use <strong>
	abp.notifications.getFormattedMessageFromUserNotification(userNotification)</strong> 
	which is internally used by showUiNotifyForUserNotification.</p>
			<p>
				<a href="/Templates">Startup templates</a> 
	include the code to show UI notifications when a push notification is 
	received.</p>
			<h3>Notification Store</h3>
			<p>Notification system uses <strong>INotificationStore</strong> to persist 
	notifications. This should be implemented in order to make notification 
	system properly working. You can implement it yourself or use <strong>
					<a href="/Pages/Documents/Zero/Overall">module-zero</a>
				</strong> which 
	already implements it.</p>
			<h3>Notification Definitions</h3>
			<p>You don't have to <strong>define</strong> a notification before usage. You can just use 
	any <strong>notification name</strong> without defining it. But, defining it 
	may bring you some additional benefits. For example, you can then 
				<strong>investigate</strong> all notifications in your application. In this case, we 
	can define a <strong>notification provider</strong> for our 
				<a href="/Pages/Documents/Module-System">module</a> as shown below:</p>
			<pre lang="cs">public class MyAppNotificationProvider : <strong>NotificationProvider</strong>
{
    public override void SetNotifications(INotificationDefinitionContext context)
    {
        context.Manager.Add(
            new NotificationDefinition(
                &quot;<strong>App.NewUserRegistered</strong>&quot;,
                <strong>displayName</strong>: new LocalizableString(&quot;NewUserRegisteredNotificationDefinition&quot;, &quot;MyLocalizationSourceName&quot;),
                <strong>permissionDependency</strong>: new SimplePermissionDependency(&quot;<strong>App.Pages.UserManagement</strong>&quot;)
                )
            );
    }
}</pre>
			<p>&quot;<strong>App.NewUserRegistered</strong>&quot; is unique name of the 
	notification. We defined a localizable <strong>displayName</strong> (then 
	we can show it while subscribing to the notification on UI). And finally, we 
	declared that this notification is available to a user only if he has &quot;<strong>App.Pages.UserManagement</strong>&quot;
				<a href="/Pages/Documents/Authorization">permission</a>. </p>
			<p>There are also some other parameters, you can investigate in the code. Only notification 
	name is <strong>required</strong> for a notification definition. </p>
			<p>After defining such a notification provider, we should register it in
				<a href="/Pages/Documents/Module-System#DocModulePreInit">PreInitialize</a> 
	event of our module, as shown below:</p>
			<pre lang="cs">public class AbpZeroTemplateCoreModule : AbpModule
{
    public override void PreInitialize()
    {
        <strong>Configuration.Notifications.Providers.Add&lt;MyAppNotificationProvider&gt;();</strong>
    }

    //...
}</pre>
			<p>Finally, you can inject and use <strong>INotificationDefinitionManager</strong> 
	in your application to get notification definitions. Then you may want to 
			prepare a automatic page to allow user to subscribe those 
			notifications.</p>

		</div>

	</body>

</html>
